home *** CD-ROM | disk | FTP | other *** search
- /* EFTH MINIX report #64 - February 1989 - termcap(3) */
-
- /*
- * termcap.c V1.1 20/7/87 agc Joypace Ltd
- *
- * Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
- * This file may be freely distributed provided that this notice
- * remains attached.
- *
- * A public domain implementation of the termcap(3) routines.
- *
- *
- *
- * Klamer Schutte V1.2 Nov. 1988
- *
- * - Can match multiple terminal names [tgetent]
- * - Removal of **area assignments [tgetstr]
- *
- * Terrence W. Holm V1.3 May, Sep, Oct. 1988
- *
- * - Correct when TERM != name and TERMCAP is defined [tgetent]
- * - Correct the comparison for the terminal name [tgetent]
- * - Correct the value of ^x escapes [tgetstr]
- * - Added %r to reverse row/column [tgoto]
- * - Fixed end of definition test [tgetnum/flag/str]
- *
- * Terrence W. Holm V1.4 Jan. 1989
- *
- * - Incorporated Klamer's V1.2 fixes into V1.3
- * - Added %d, (old %d is now %2) [tgoto]
- * - Allow '#' comments in definition file [tgetent]
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <string.h>
-
- char *capab = NULL; /* the capability itself */
-
- /* The following are not yet used. */
- extern short ospeed; /* output speed */
- extern char PC; /* padding character */
- extern char *BC; /* back cursor movement */
- extern char *UP; /* up cursor movement */
-
-
- #ifndef __STDC__
- extern char *getenv();
- extern FILE *fopen();
- #else
- /* pick up proto from <std.h> */
- #endif
-
-
- /*
- * tgetent - get the termcap entry for terminal name, and put it
- * in bp (which must be an array of 1024 chars). Returns 1 if
- * termcap entry found, 0 if not found, and -1 if file not found.
- */
-
- int
- tgetent(bp, name)
- char *bp;
- _CONST char *name;
- {
- FILE *fp;
- char *file;
- char *term;
- short len = strlen(name);
-
- capab = bp;
-
- /* If TERMCAP begins with a '/' then use TERMCAP as the path */
- /* name of the termcap definitions file. If TERMCAP is a */
- /* definition and TERM equals "name" then use TERMCAP as the */
- /* definition. Otherwise use "/etc/termcap" as the path name. */
-
- if ( (file = getenv("TERMCAP")) == NULL )
- file = "/etc/termcap";
- else if ( *file != '/' )
- if ( (term = getenv("TERM")) != NULL && strcmp(term, name) == 0 ) {
- *bp = '\0';
- strncat( bp, file, 1023 );
- return(1);
- } else
- file = "/etc/termcap";
-
- if ((fp = fopen(file, "r")) == (FILE *) NULL) {
- capab = NULL; /* no valid termcap */
- return(-1);
- }
-
- for (;;) {
- /* Read in each definition */
- int def_len = 0;
- char *cp = bp;
-
- do {
- if ( fgets(&bp[def_len], 1024-def_len, fp) == NULL ) {
- fclose(fp);
- capab = NULL; /* no valid termcap */
- return(0);
- }
-
- def_len = strlen(bp) - 2;
- } while( bp[def_len] == '\\' );
-
- while ( isspace(*cp) )
- cp++;
-
- /* Comment lines start with a '#' */
- if ( *cp == '#' )
- continue;
-
- /* See if any of the terminal names in this definition */
- /* match "name". */
-
- do {
- if ( strncmp(name, cp, len) == 0 &&
- ( cp[len] == '|' || cp[len] == ':' ) ) {
- fclose(fp);
- return(1);
- }
-
- while( (*cp) && (*cp != '|') && (*cp != ':'))
- cp++;
- } while( *cp++ == '|');
- }
- }
-
-
-
- /*
- * tgetnum - get the numeric terminal capability corresponding
- * to id. Returns the value, -1 if invalid.
- */
-
- int
- tgetnum(id)
- _CONST char *id;
- {
- register char *cp = capab;
-
- if (cp == NULL || id == NULL)
- return(-1);
-
- for(;;) {
- while (*cp++ != ':')
- if (cp[-1] == '\0')
- return(-1);
-
- while (isspace(*cp))
- cp++;
-
- if (strncmp(cp, id, 2) == 0 && cp[2] == '#' )
- return( atoi(cp+3) );
- }
- }
-
-
-
- /*
- * tgetflag - get the boolean flag corresponding to id. Returns -1
- * if invalid, 0 if the flag is not in termcap entry, or 1 if it is
- * present.
- */
-
- int
- tgetflag(id)
- _CONST char *id;
- {
- register char *cp = capab;
-
- if (cp == NULL || id == NULL)
- return(-1);
-
- for (;;) {
- while (*cp++ != ':')
- if (cp[-1] == '\0')
- return(0);
-
- while (isspace(*cp))
- cp++;
-
- if (strncmp(cp, id, 2) == 0)
- return(1);
- }
- }
-
-
-
- /*
- * tgetstr - get the string capability corresponding to id and place
- * it in area (advancing area at same time). Expand escape sequences
- * etc. Returns the string, or NULL if it can't do it.
- */
-
- char *
- tgetstr(id, area)
- _CONST char *id;
- char **area;
- {
- register char *cp = capab;
- register char *wsp = *area; /* workspace pointer */
-
- if (cp == NULL || id == NULL)
- return(NULL);
-
- for (;;) {
- while (*cp++ != ':')
- if (cp[-1] == '\0')
- return(NULL);
-
- while (isspace(*cp))
- cp++;
-
- if (strncmp(cp, id, 2) == 0 && cp[2] == '=' ) {
- for (cp+=3; *cp && *cp != ':' ; wsp++, cp++)
- switch(*cp) {
- case '^' :
- *wsp = *++cp - '@';
- break;
-
- case '\\' :
- switch(*++cp) {
- case 'E' :
- *wsp = '\033';
- break;
- case 'n' :
- *wsp = '\n';
- break;
- case 'r' :
- *wsp = '\r';
- break;
- case 't' :
- *wsp = '\t';
- break;
- case 'b' :
- *wsp = '\b';
- break;
- case 'f' :
- *wsp = '\f';
- break;
- case '0' :
- case '1' :
- case '2' :
- case '3' :
- {
- int i;
- int t = 0;
- for (i=0; i<3 &&
- isdigit(*cp) ; ++i, ++cp)
- t = t * 8 + *cp - '0';
- *wsp = t;
- cp--;
- break;
- }
- default:
- *wsp = *cp;
- }
- break;
-
- default :
- *wsp = *cp;
- }
-
- *wsp++ = '\0';
-
- {
- char *ret = *area;
- *area = wsp;
- return(ret);
- }
- }
- } /* end for(;;) */
- }
-
-
-
- /*
- * tgoto - given the cursor motion string cm, make up the string
- * for the cursor to go to (destcol, destline), and return the string.
- * Returns "OOPS" if something's gone wrong, or the string otherwise.
- */
-
- char *
- tgoto(cm, destcol, destline)
- _CONST char *cm;
- int destcol;
- int destline;
- {
- static char ret[24];
- char *rp = ret;
- int incr = 0;
- int argno = 0;
- int numval;
-
- for ( ; *cm ; cm++) {
- if ( *cm == '%' ) {
- switch(*++cm) {
- case 'i' :
- incr = 1;
- break;
-
- case 'r' :
- argno = 1;
- break;
-
- case '+' :
- numval = (argno == 0 ? destline : destcol);
- *rp++ = numval + incr + *++cm;
- argno = 1 - argno;
- break;
-
- case '2' :
- numval = (argno == 0 ? destline : destcol);
- numval = (numval + incr) % 100;
- *rp++ = '0' + (numval/10);
- *rp++ = '0' + (numval%10);
- argno = 1 - argno;
- break;
-
- case 'd' :
- numval = (argno == 0 ? destline : destcol);
- numval = (numval + incr) % 1000;
- if ( numval > 99 )
- *rp++ = '0' + (numval/100);
- if ( numval > 9 )
- *rp++ = '0' + (numval/10) % 10;
- *rp++ = '0' + (numval%10);
- argno = 1 - argno;
- break;
-
- case '%' :
- *rp++ = '%';
- break;
-
- default :
- return( "OOPS" );
- }
-
- } else
- *rp++ = *cm;
- }
-
- *rp = '\0';
- return(ret);
- }
-
-
-
- /*
- * tputs - put the string cp out onto the terminal, using the function
- * outc. This should do padding for the terminal, but I can't find a
- * terminal that needs padding at the moment...
- */
-
- int
- tputs(cp, affcnt, outc)
- _CONST register char *cp;
- int affcnt;
- int (*outc)();
- {
- if (cp == NULL)
- return(1);
- /* do any padding interpretation - left null for MINIX just now */
- while (*cp)
- (*outc)(*cp++);
- return(1);
- }
-